import network
import usocket as socket
from machine import Pin
import time
import re

print("ESP32 HTTP引脚控制服务器")
# 配置参数
WIFI_SSID = "OrayBox"  # 替换为实际WiFi名称
WIFI_PASSWORD = "fullhouse10JQKA"  # 替换为实际WiFi密码
HTTP_PORT = 8080  # 端口改为8080

# 存储已初始化的引脚（避免重复创建）
pins = {}
led_pin = Pin(2, Pin.OUT)
pins[2] = led_pin

# WiFi连接函数
def connect_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print(f"正在连接WiFi: {ssid}")
        wlan.connect(ssid, password)

        # 等待连接（最多15秒）
        for _ in range(15):
            led_pin.value(1)
            if wlan.isconnected():
                break
            print("连接中...")
            time.sleep(1)
            led_pin.value(0)

        if not wlan.isconnected():
            raise RuntimeError("WiFi连接失败，请检查配置")

    ip = wlan.ifconfig()[0]
    print(f"WiFi连接成功，IP地址: {ip}")
    print(f"控制URL格式: http://{ip}:{HTTP_PORT}/<引脚号>/<on/off>")
    return ip


# 解析URL路径，返回(pin, action)或None（错误）
def parse_path(path):
    # 正则匹配路径格式: /数字/on 或 /数字/off
    pattern = r'^/(\d+)/(on|off)$'
    match = re.match(pattern, path)
    if not match:
        return None

    pin_num = int(match.group(1))
    action = match.group(2)

    # 检查引脚号是否在合理范围（ESP32常用引脚0-33）
    if 0 <= pin_num <= 33:
        return (pin_num, action)
    else:
        return None


# 处理引脚控制
def control_pin(pin_num, action):
    # 初始化引脚（若未初始化）
    if pin_num not in pins:
        pins[pin_num] = Pin(pin_num, Pin.OUT)  # 设为输出模式

    # 执行动作
    if action == "on":
        pins[pin_num].value(1)  # 拉高
        return True, f"引脚{pin_num}已拉高"
    elif action == "off":
        pins[pin_num].value(0)  # 拉低
        return True, f"引脚{pin_num}已拉低"
    else:
        return False, "无效动作"

def create_response(status_code, content):
    headers = f"HTTP/1.1 {status_code}\r\nContent-Type: text/html; charset=utf-8\r\n\r\n"
    return headers + content

# 启动HTTP服务器
def run_http_server(ip):
    addr = socket.getaddrinfo(ip, HTTP_PORT)[0][-1]
    s = socket.socket()
    s.bind(addr)
    s.listen(5)  # 支持最多5个并发连接等待
    print(f"HTTP服务器已启动，端口: {HTTP_PORT}")

    try:
        while True:
            cl, addr = s.accept()
            print(f"收到连接: {addr}")

            # 读取请求（最多1024字节）
            request = cl.recv(1024).decode().strip()
            print(f"请求内容:\n{request}")

            # 解析请求路径（提取GET后的路径）
            path = None
            if request.startswith("GET "):
                path = request.split(" ")[1]  # 例如 "GET /2/on HTTP/1.1" → 提取 "/2/on"

            # 处理路径
            if not path:
                response = create_response("400 Bad Request", "无效请求格式")
            else:
                parsed = parse_path(path)
                if not parsed:
                    error_msg = f"无效路径: {path}<br>正确格式: /<引脚号>/<on/off>"
                else:
                    pin_num, action = parsed
                    success, msg = control_pin(pin_num, action)
                    if success:
                        response = create_response("200 OK", msg)
                    else:
                        response = create_response("500 Internal Error", f"控制失败: {msg}")

            # 发送响应并关闭连接
            cl.send(response)
            cl.close()
            print("连接已关闭\n")

    except Exception as e:
        print(f"服务器错误: {e}")
    finally:
        s.close()


# 主程序
if __name__ == "__main__":
    try:
        ip = connect_wifi(WIFI_SSID, WIFI_PASSWORD)
        if ip:
            control_pin(2, "on")
        run_http_server(ip)
    except Exception as e:
        print(f"程序错误: {e}")
    finally:
        print("程序退出")